package Envo 
{
	import Envo.Assets.PlayerFloor;
	import flash.display.MovieClip;
	import flash.geom.Rectangle;
	/**
	 * ...
	 * @author Sam Morrison
	 */
	public class Physics 
	{
		// Game reference
		private var game:Game;							// Game variable
		
		// Constants
		public const HORIZONTAL_SPEED:int = 8;			// Speed left and right
		public const GRAVITY:int = 2;					// Gravity constant
		public const MAX_JUMPS:int = 1;					// Amount of jumps
		
		public const TOP_SPEED:int = 8;					// Top speed
		
		public const HORIZONTAL_ACCELERATION:int = 1;
		
		public const INCREASED_TOP_SPEED:int = 12;		// Top speed on speed blocks
		public const JUMP_HEIGHT:int = 20;				// Jump height
		public const INCREASED_JUMP_HEIGHT:int = 35;	// Jump height on bounce blocks
		public const WALL_SLIDE_SPEED:int = 7;
		
		
		public function Physics(game:Game) 
		{
			this.game = game;
		}
		
		public function update(player:Player, level:Level):void
		{
			// Moves player to the left or the right
			if (player.movingLeft == true)
			{
				player.horizontalAcceleration -= HORIZONTAL_ACCELERATION;
				
				if (player.horizontalAcceleration < -HORIZONTAL_SPEED)
				{
					player.horizontalVelocity = -HORIZONTAL_SPEED;
					player.horizontalAcceleration = -HORIZONTAL_SPEED;
				}
				else
				{
					player.horizontalVelocity = player.horizontalAcceleration;
				}
			}
			
			if (player.movingRight == true)
			{
				player.horizontalAcceleration += HORIZONTAL_ACCELERATION;
				
				if (player.horizontalAcceleration > HORIZONTAL_SPEED)
				{
					player.horizontalVelocity = HORIZONTAL_SPEED;
					player.horizontalAcceleration = HORIZONTAL_SPEED;
				}
				else
				{
					player.horizontalVelocity = player.horizontalAcceleration;
				}
			}
			
			if(player.movingLeft == false && player.movingRight == false)
			{
				
				
				// Horizontal Drag
				if (player.horizontalAcceleration > 0)
				{
					player.horizontalAcceleration--;
					player.horizontalVelocity = player.horizontalAcceleration;
				}
				else if (player.horizontalAcceleration < 0)
				{
					player.horizontalAcceleration++;
					player.horizontalVelocity = player.horizontalAcceleration;
				}
				else
				{
					player.horizontalAcceleration = 0;
					player.horizontalVelocity = player.horizontalAcceleration;
				}
			}
			
			if (player.verticalAcceleration <= 20)
			{
				player.verticalAcceleration += GRAVITY;
			}
			
			// Wall Sliding
			if (player.collidingHorizontal == "left"
				|| player.collidingHorizontal == "right")
			{
				// Give the player another jump
				player.currentJumps = MAX_JUMPS;
				
				// Set a constant wall slide speed
				if(player.verticalAcceleration > 0)
				{
					player.verticalAcceleration = WALL_SLIDE_SPEED;
				}
			}
			
			if (player.jumping == true)
			{
				// Accelerate player upwards when jump button pressed
				if (player.currentJumps != 0 && player.jumpReleased == true)
				{
					// Set current acceleration to set jump initial velocity
					player.verticalAcceleration = -JUMP_HEIGHT;
					player.y += player.verticalAcceleration;
					
					
					// Decrease number of jumps
					player.currentJumps--;
				}
				
				// Reset Jump Released variable
				player.jumpReleased = false;
			}
			
			player.y += player.verticalAcceleration;
			
			// Checks horizontal collisions
			collisionsVertical(player, level.SolidFloors);
			
			// Moves player
			player.x += player.horizontalVelocity;
			
			// Checks horizontal collisions
			collisionsHorizontal(player, level.SolidFloors);
		}
		
		public function collisionsVertical(player:Player, floorArray:Array):void
		{
			for ( var i:int = 0; i < floorArray.length; i++)
			{
				// Get rectangle bounding boxes for the level and the player
				var floorRectangle:Rectangle = floorArray[i].getRect(game);
				var playerRectangle:Rectangle = player.mc_boundingBox.getRect(game);
				
					// Vertical collisions
					if (((playerRectangle.bottom > floorRectangle.top 
						&& playerRectangle.top < floorRectangle.top) 
						|| (playerRectangle.top < floorRectangle.bottom
						&& playerRectangle.top > floorRectangle.top)) 
						&& ((playerRectangle.right > floorRectangle.left
						&& playerRectangle.right < floorRectangle.right) 
						|| (playerRectangle.left < floorRectangle.right
						&& playerRectangle.left > floorRectangle.left)))
				   
				   {
						// Bottom of player to top of level
						if (playerRectangle.bottom > floorRectangle.top
							&& playerRectangle.top < floorRectangle.top)
						{
							// Set player outside of block
							player.y = floorRectangle.top - player.mc_boundingBox.height;
							
							// Set current acceleration to  0 and reset the max amount of jumps
							player.verticalAcceleration = GRAVITY;
							player.currentJumps = MAX_JUMPS;
							
							player.collidingVertical = "bottom";
							break;
							
						}
						// Top of player to bottom of level
						if (playerRectangle.top < floorRectangle.bottom
							&& playerRectangle.top > floorRectangle.top)
						{
							// Set player outside of block
							player.y = floorRectangle.bottom;
							
							// Set current acceleration to 0
							player.verticalAcceleration = 0;
							
							player.collidingVertical = "top";
							break;
						}
						
					}
					else
					{
						player.collidingVertical = "none";
					}
			}
		}
		
		public function collisionsHorizontal(player:Player, floorArray:Array):void
		{
			for ( var i:int = 0; i < floorArray.length; i++)
			{
				// Get rectangle bounding boxes for the level and the player
				var floorRectangle:Rectangle = floorArray[i].getRect(game);
				var playerRectangle:Rectangle = player.mc_boundingBox.getRect(game);
				
				// if things break down, try adding a condition where the block top or bottom is equal
				// to a blocks top or bottom
				if (((playerRectangle.right > floorRectangle.left 
					&& playerRectangle.left < floorRectangle.left) 
					|| (playerRectangle.left < floorRectangle.right
					&& playerRectangle.left > floorRectangle.left)) 
					&& ((playerRectangle.bottom > floorRectangle.top 
					&& playerRectangle.bottom < floorRectangle.bottom ) 
					|| (playerRectangle.top < floorRectangle.bottom  
					&& playerRectangle.top > floorRectangle.top) 
					|| ((playerRectangle.top <= floorRectangle.top) 
					&& (playerRectangle.bottom >= floorRectangle.bottom))))
				{
					
					// If the player's right side goes through the left side of a block
					if (playerRectangle.right > floorRectangle.left 
						&& playerRectangle.left < floorRectangle.left )
					{
						player.horizontalVelocity = 0;										// Set the x velocity to 0
						player.horizontalAcceleration = 0;
						player.x = floorRectangle.left - player.mc_boundingBox.width;		// Place the player just left of the block
						player.collidingHorizontal = "right";
						
						break;
					}
					
					// If the player's left side goes through the right side of a block
					if (playerRectangle.left < floorRectangle.right 
						&& playerRectangle.left > floorRectangle.left )
					{
						player.horizontalVelocity = 0;										// Set the x velocity to 0
						player.horizontalAcceleration = 0;
						player.x = floorRectangle.right;									// Place the player just right of the block
						player.collidingHorizontal = "left";
						break;
					}
					
				}
				else
				{
					player.collidingHorizontal = "none";
				}
			}
		}
	}
}